//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2013 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_FUNCTORS_TRANSFORM_BINARY_H_
#define _BUOLA_FUNCTORS_TRANSFORM_BINARY_H_

#include <buola/buola.h>

namespace buola { namespace fn {

///\addtogroup functors
///@{

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// tag class for binary functions which can be used as transformations
///
/// This contains several function classes which can be used to transform two values into a single value. Among others, it
/// contains functions to perform arithmetic operations on two value.
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct GBinaryTransform {};
    
///\name Arithmetic binary transformations
//@{

/////////////////////////////////////////////////////////////////////////////////////////////////
///
/// add transformation
///
/// Evaluated with two arguments, returns the result of adding the two arguments
///
/////////////////////////////////////////////////////////////////////////////////////////////////
struct AAdd : public GBinaryTransform
{
    ///returns \p pLH+pRH
    template<typename tParam>
    tParam operator()(const tParam &pLH,const tParam &pRH) const
    {
        return pLH+pRH;
    }
};

/////////////////////////////////////////////////////////////////////////////////////////////////
///
/// subtract transformation
///
/// Evaluated with two arguments, returns the result of subtracting one argument from the other
///
/////////////////////////////////////////////////////////////////////////////////////////////////
struct ASubtract : public GBinaryTransform
{
    ///returns \p pLH-pRH
    template<typename tParam>
    tParam operator()(const tParam &pLH,const tParam &pRH) const
    {
        return pLH-pRH;
    }
};

/////////////////////////////////////////////////////////////////////////////////////////////////
///
/// multiply transformation
///
/// Evaluated with two arguments, returns the result of multiplying the two arguments
///
/////////////////////////////////////////////////////////////////////////////////////////////////
struct AMultiply : public GBinaryTransform
{
    ///returns \p pLH*pRH
    template<typename tParam>
    tParam operator()(const tParam &pLH,const tParam &pRH) const
    {
        return pLH*pRH;
    }
};

/////////////////////////////////////////////////////////////////////////////////////////////////
///
/// divide transformation
///
/// Evaluated with two arguments, returns the result of dividing one argument by the other
///
/////////////////////////////////////////////////////////////////////////////////////////////////
struct ADivide : public GBinaryTransform
{
    ///returns \p pLH/pRH
    template<typename tParam>
    tParam operator()(const tParam &pLH,const tParam &pRH) const
    {
        return pLH/pRH;
    }
};

//@}

///@}

/*namespace fn*/ } /*namespace buola*/ }

#endif
